/*
 * Create Date: 2018.6.7 convert from java version
 * Author:  macroLu
 * Comment: groovy Dao Utils
 */
package com.macrolab.util;

import com.alibaba.druid.pool.DruidDataSource;
import groovy.sql.GroovyRowResult;
import groovy.sql.Sql;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.sql.SQLException;
import java.util.List;
import java.util.Map;


public class GDAO {
    private static final Logger log = LoggerFactory.getLogger(GDAO.class);

    boolean showSql = false;
    Sql db;

    public boolean isShowSql() {
        return showSql;
    }

    public void setShowSql(boolean showSql) {
        this.showSql = showSql;
    }

    public GDAO(DruidDataSource ds, boolean showSql) {
        db = new Sql(ds);
        this.showSql = showSql;
    }

    /**
     * 若要项目设置showSql，则显示sql语句
     * trim sql 中的 \n 及多行sql的空白
     *
     * @param sql
     * @return
     */

    public void debugShowSql(String sql) {
        if (showSql) {
            String lines[] = sql.split("\n");
            for (int i = 0; i < lines.length; i++) {
                log.debug(lines[i]);
            }
        }
    }


    /**
     * 通用查询
     *
     * @param sql
     * @return 记录数组
     */
    public List<GroovyRowResult> query(String sql) throws SQLException {
        debugShowSql(sql);
        List<GroovyRowResult> rows = db.rows(sql);
        return rows;
    }


    /**
     * MySql版分页查询
     *
     * @param sql
     * @param pageSize 页大小
     * @param pageNo   页号 从第1页开始
     * @return
     */
    public List<GroovyRowResult> queryPagesMySql(String sql, int pageSize, int pageNo) throws SQLException {
        sql += "LIMIT ${pageSize * (pageNo - 1)},${pageSize}";
        debugShowSql(sql);
        List<GroovyRowResult> rows = db.rows(sql);
        return rows;
    }

//    /**
//     * Oracle版分页查询
//     *
//     * @param sql      可以排序
//     * @param pageSize 页大小
//     * @param pageNo   页号 从第1页开始
//     * @return
//     */
//    def queryPagesOracle(String sql, int pageSize, int pageNo) {
//        String pageSql = "" ";
//        select *
//                from(select rownum rownum_in_pages, row_in_pages. * from($ {
//            sql
//        } )row_in_pages)
//        where rownum_in_pages BETWEEN $ {
//            pageSize * (pageNo - 1)
//        } and $ {
//            pageSize * (pageNo - 1) + pageSize
//        } "" "
//        debugShowSql(sql);
//        def rows = db.rows(pageSql);
//        rows;
//    }

    /**
     * 通用查询第一条记录
     *
     * @param sql
     * @return
     */
    public GroovyRowResult queryFirstrow(String sql) throws SQLException {
        debugShowSql(sql);
        GroovyRowResult rows = db.firstRow(sql);
        return rows;
    }

    /**
     * insert,update,delete
     *
     * @param sql
     * @return boolean 处理成功失败
     */
    public boolean execute(String sql) throws SQLException {
        debugShowSql(sql);
        return db.execute(sql);
    }

    /**
     * update
     *
     * @param sql
     * @return 变更的记录数量
     */
    public int executeUpdate(String sql) throws SQLException {
        debugShowSql(sql);
        return db.executeUpdate(sql);
    }


//    /**
//     * 使用观察模式封装数据对象,用于表数据的更新
//     *
//     * @param data  Map类型的表字段取值
//     * @param table 表名
//     * @return
//     */
//    def omWrapping(data, table) {
//        if (data == null || data instanceof ObservableMap) {
//            return data;
//        } else {
//            def om = new ObservableMap(data);
//            om._table = table;
//            om._update_fields = []as Set;
//            def updateListener = {evt ->
//                    log.debug("table value changed: ${evt.source['_table']}.${evt['propertyName']} from [${evt['oldValue']}] to [${evt['newValue']}] ")
//            if (evt instanceof ObservableMap.PropertyUpdatedEvent) {
//                evt.source._update_fields << evt.propertyName;
//            }
//            }as PropertyChangeListener
//            om.addPropertyChangeListener(updateListener);
//            return om;
//        }
//    }

//    /**
//     * @param data  采用omWrapping() 封装的 ObservableMap 数据对象
//     * @param where Map 用于定位要更新的数据（一般用主键）
//     * @return 返回更新数据的数量
//     * @see GDAO#omWrapping
//     * <p>
//     * 对data中有数据变动的字段执行update语句
//     */
//    def omUpdate(data, Map where) {
//        if (!data || !data._table) return false;
//        if (!data._update_fields) return true;
//        def params = [];
//        String updateSql = "update ${data._table} set ";
//        for (String field in data._update_fields){
//            if (data[field] != null) {
//                updateSql += (params ? ', ' : '') + " $field = ?";
//                params << data[field];
//            }
//        }
//        updateSql += ' where 1=1 '
//        where.each {
//            k, v ->
//                    updateSql += " and ${k} = ?"
//            params << v
//        }
//        if (showSql) {
//            log.debug "omUpdate sql: $updateSql    params: $params"
//        }
//        return db.executeUpdate(updateSql, params)
//    }

    /**
     * 替代insert功能，用于id自增类主键表。如mysql中
     *
     * @param tableName
     * @param data
     * @return
     */
    public  Map saveData(String tableName, Map data) throws SQLException {
        db.dataSet(tableName).add(data);
        data.put("id", db.firstRow("select last_insert_id() id").get("id"));
        return data;
    }

    /**
     * 用groovy的 sql.add() 方法，向数据表里写数据
     *
     * @param tableName
     * @param data
     * @return
     */
    public  void createData(String tableName, Map data) throws SQLException {
        db.dataSet(tableName).add(data);
    }


//    public void updateTableById(String tableName, Map fields, Map data) {
//        def params = [];
//        String updateSql = "update " + tableName + " set ";
//        fields.forEach((k, v) ->
//                        updateSql += (params ? ', ' : '') + " $it = ?"
//                System.out.println("key:value = " + k + ":" + v)
//        );
//
//
//
//        .each {
//            if (data[it] != null) {
//                updateSql += (params ? ', ' : '') + " $it = ?"
//                params << data[it]
//            }
//        }
//
//        if (!params || !data.id) return false
//        updateSql += ' where id = ?'
//        params << data.id
//
//        println "updateTableById sql: $updateSql   params: $params"
//
//        1 == db.executeUpdate(updateSql, params)
//    }

}
